package com.goldgov.oauth2filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.goldgov.config.FilterProperties;
import com.goldgov.kduck.cache.CacheHelper;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * oauth2回调方法
 * @author guor
 */
@Controller
public class Oauth2Controller {
    @Autowired
    FilterProperties filterProperties;

    /**
     * 认证成功后回调该方法：<br/>
     * code：为code授权模式返回的授权码
     * state：为请求地址，用于认证成功后继续访问该地址
     * @param request
     * @return vlogin为模拟登录界面的view名
     * @throws IOException
     */
    @RequestMapping("/oauth/callback")
    public String callback(HttpServletRequest request) throws IOException {
        if(isWeiXinCallback(request)){

            String username = request.getParameter("username");
            String state = request.getParameter("state");

            request.setAttribute("loginName",username);
            long loginPassword = System.currentTimeMillis();
            //模拟登录的密码，使用缓存方法记录，注意分布式或负载时，需要使用Redis的缓存
            request.setAttribute("loginPassword",loginPassword);
            //模拟密码保存60秒
            CacheHelper.put("loginPassword",loginPassword+"",60);
            //登录成功后跳转的地址
            request.setAttribute("service",state);
            return "mocklogin";
        }
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        if(StringUtils.isEmpty(code)){
            return "Not fond code.";
        }
        CloseableHttpClient httpClient = HttpClients.custom()
                .build();
        HttpPost httpPost = new HttpPost(filterProperties.getOauth2Server()+"/oauth/token");
        List<NameValuePair> formParams = new ArrayList<NameValuePair>();
        //表单参数
        formParams.add(new BasicNameValuePair("client_id", filterProperties.getClientId()));
        formParams.add(new BasicNameValuePair("client_secret", filterProperties.getClientSecret()));
        formParams.add(new BasicNameValuePair("grant_type", "authorization_code"));
        formParams.add(new BasicNameValuePair("redirect_uri", filterProperties.getRedirectUri()));
        formParams.add(new BasicNameValuePair("code", code));
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, "utf-8");
        httpPost.setEntity(entity);
        CloseableHttpResponse response = httpClient.execute(httpPost);
        ObjectMapper objectMapper = new ObjectMapper();
        //获取token相关信息
        Map<String,String> map = objectMapper.readValue(EntityUtils.toString(response.getEntity()), Map.class);
        String access_token = map.get("access_token");
        //获取用户信息
        String userinfo = getUserinfo(access_token);
        //解析用户信息
        map = objectMapper.readValue(userinfo, Map.class);
//        request.getSession().setAttribute("ISLOGIN","true");
        request.getSession().setAttribute("USERINFO",userinfo);
//        request.setAttribute("loginName",map.get("username"));
        //获取当前认证人的账号，进行模拟登录 FIXME 写死用于测试，正式环境用上面注释那行
        request.setAttribute("loginName","admin");
        long loginPassword = System.currentTimeMillis();
        //模拟登录的密码，使用缓存方法记录，注意分布式或负载时，需要使用Redis的缓存
        request.setAttribute("loginPassword",loginPassword);
        //模拟密码保存60秒
        CacheHelper.put(map.get("username")+"_loginPassword",loginPassword+"",60);
        //登录成功后跳转的地址
        request.setAttribute("service",state);
        return "mocklogin";
    }

    //FIXME 根据真实参数判断是否是微信登录
    private boolean isWeiXinCallback(HttpServletRequest request) {
        return StringUtils.hasText(request.getParameter("uid"));
    }

    /**
     * 从统一认证服务器获取用户信息
     * @param access_token
     * @return
     * @throws IOException
     */
    private String getUserinfo(String access_token) throws IOException {
        CloseableHttpClient httpClient = HttpClients.custom()
                .build();
        HttpPost httpPost = new HttpPost(filterProperties.getOauth2Server()+"/userinfo");
        List<NameValuePair> formParams = new ArrayList<NameValuePair>();
        //表单参数
        formParams.add(new BasicNameValuePair("access_token", access_token));
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, "utf-8");
        httpPost.setEntity(entity);
        CloseableHttpResponse response = httpClient.execute(httpPost);
        return EntityUtils.toString(response.getEntity());
    }
}
